""" This module provides support for compressed file formats such as Rar."""

import os.path, sys, posixpath
import pyflag.pyflaglog as pyflaglog
from pyflag.Scanner import *
from pyflag.FileSystem import File
import pyflag.Magic as Magic
import time, re, os
import StringIO
import pyflag.Scanner as Scanner
import plugins.DiskForensics.DiskForensics as DiskForensics
import pyflag.Store as Store
import pyflag.Time as Time
import rarfile
import pyflag.conf


class RarScan(GenScanFactory):
    """ Recurse into Rar Files """
    order 	= 99
    default 	= True
    depends 	= "TypeScan"
    group 	= "CompressedFile"
    
    def destroy(self):
        pass
    
    class Scan(StoreAndScanType):
        types = (
            'application/x-rar',
            )
	
        def external_process(self,fd):
            archive = rarfile.RarFile(fd.name)

	    ## List all the files in the rar file:
            inodes = []
            dircount = 0
            namelist = archive.namelist()

	    for i in range(len(namelist)):
                ## If the entry corresponds to just a directory we ignore it.
                if not os.path.basename(namelist[i]): continue

		info = archive.infolist()[i]
                ## Add the file into the VFS
                self.ddfs.VFSCreate(
                    self.inode, "R%s" % i, namelist[i],
                    size = info.file_size,
                    mtime = 0)
		
		new_inode = "%s|R%s" % (self.inode, i)
                inodes.append(new_inode)
	    for inode in inodes:
                ## Scan the new file using the scanner train:
                try:
		    fd = self.ddfs.open(inode = inode)
            	    Scanner.scanfile(self.ddfs, fd, self.factories)
		except Exception:
		    pass


class RarFile(File):
    """ A file like object to read files from within zip files.

    We essentially decompress the file on the disk because the file
    may be exceptionally large.
    """
    specifier = 'R'
    
    def __init__(self, case, fd, inode):
        File.__init__(self, case, fd, inode)
	self.fd.cache()
	
	parts = inode.split('|')

	config = pyflag.conf.ConfObject()
	path = "/%s/case_%s/%s_%s" % (config.RESULTDIR, case, parts[0], parts[1])
	path = os.path.normpath(path)
	rf = rarfile.RarFile(path)
	
	i = int(parts[-1][1:])
	namelist = rf.namelist()
	self.readptr = 0
	self.data = rf.read(namelist[i])
	

    def read(self, length = None):
	try:
	    return File.read(self, length)
	except IOError:
	    pass
	
	if length:
	    temp = self.data[self.readptr : self.readptr + length]
	    self.readptr += length
	    return temp
	else: return self.data 


    def close(self):
        pass
